home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
ansi
/
isansi
/
isansi.a86
next >
Wrap
Text File
|
1994-06-17
|
9KB
|
288 lines
;ISITANSI - check if the CON device is ANSI compatible.
;Just sends a DSR request and takes any terminated input as
;the answer. If it is of the form <CSI>n;nR then it returns
;with ERRORLEVEL 0 indicating ANSI.SYS is loaded. Otherwise
;it returns with ERRORLEVEL 1. If DOS error, ERRORLEVEL is 2.
;
;Here is a sample test program
;
;@echo off
;rem ;R-U-ANSI.BAT
;rem ;Test program for ISANSI.COM in the Assembly Language section
;rem ;of the IBMPRO forum on Compuserve. Rename it to ISITANSI.COM.
;rem ;Author John Lene Comeau, ICT, PO Box 100632, Ft. Laud. FL 33310
;rem ;Specialists in Device Drivers and Utilities on VAX/VMS, PDP/RSX,
;rem ;and PC/DOS platforms. 70641,57 on Compuserve.
;rem ;Internet address jcomeau@world.std.com
;isitansi
;cls
;if errorlevel 2 echo I don't know, there was a program error.
;if errorlevel 2 goto exit
;if errorlevel 1 echo No, I'm not.
;if errorlevel 1 goto exit
;if errorlevel 0 echo Yes, I am.
;:exit
;
debug equ 1 ;set to 0 when finished debugging
;
doscall macro
clc ;can't trust carry reg to always be cleared if success
int 21h ;give DOS the reins
#em
;
_byte equ -1 ;for use with stack variables
esc equ 27
csi equ 155 ;C1 (eight-bit) code for <ESC>[
buffer equ 254*_byte ;for buffer on stack
jmp main
dsr: db esc,'[6n$'
;tables for use with bounds_check routine:
tbl1: db 1,esc,1,csi,8,255,0
;even-numbered tables are routines to call if within bounds:
tbl2: dw escroutine,csiroutine
tbl3: db 1,'R',4,';',8,'0'-1,9,'9',5,255,0
;
main:
call init_buffer ;set up buffer on stack
mov dx,dsr ;point to DSR string
mov ah,9 ;and load code for DOS console write
doscall ;interrupt DOS for service
jc error2 ;quit if DOS error
call read_answer ;raw mode read no echo with timeout
jz error1 ;quit if nothing returned
jc error2
mov si,di ;point SI to buffer
mov cx,ax ;get byte count
lodsb ;get the first byte
dec cx ;dec the count
jcxz error1 ;quit if that's all there was
mov bx,tbl1 ;load table into BX
call bounds_check ;see if the char is acceptable
jc error2 ;quit if program error
js error1 ;ditto if bad character
call tbl2[bx] ;call appropriate routine
jc error2
js error1
dec cx ;dec for next LODSB
i1: lodsb ;next char
mov bx,tbl3 ;if we got this far, look for 'R'
call bounds_check
jc error2 ;treat errors the same
js error1
jz success ;finish up if R found
loop i1 ;loop till done
jmp error1 ;error at end of string
success:
mov ax,4c00h ;ERRORLEVEL 0, success
doscall ;exit to DOS
error1:
mov ax,4c01h ;ERRORLEVEL 1
doscall ;exit
error2:
mov ax,4c02h ;ERRORLEVEL 2
doscall
escroutine:
;if found ESC, next char must be "[" or else forget it...
lodsb ;get the following character
dec cx ;decrement the character count
js ret ;quit if underflow
cmp al,'[' ;is it left square bracket?
jz ret ;jump if so
or al,80h ;else set sign flag to show syntax error
csiroutine:
;if 8-bit character C1 was received, nothing more to do...
ret ;return to main routine
bounds_check:
;This routine is passed a character in AL and a table address in
;BX. The table consists of word entries, each with the low byte
;containing an action code and the high byte a character code. The
;action codes are:
; 0 - end of table
; 1 - char is legal
; 2 - chars less than or equal to this is legal
; 3 - chars greater than this are legal
; 4 - char is ignored
; 5 - chars <= are ignored
; 6 - chars > are ignored
; 7 - char is illegal
; 8 - chars <= are illegal
; 9 - chars > are illegal
;returns S set if char is illegal
;Z set if char is legal
;C set if passed bad parameters (program error) or reached end of table
;no flags if char is to be ignored
;doesn't change AX, but BX is returned as word offset to entry where
;match occurred. All other regs are saved.
push dx ;save aux register
push ax ;save character
push bx ;save start of table
mov ah,10 ;highest legal action code is 9
jmp b2 ;skip cleanup routine on first entry
b1: xchg bx,dx ;swap regs back where they belong
inc bx ;and point to next word entry
b2: cmp [bx],ah ;past highest legal action code?
jnc b96 ;if so, quit
mov dl,[bx] ;else get the action code
xor dh,dh ;make word pointer
shl dx,1
inc bx ;point to character code
cmp al,[bx] ;compare current character to it
xchg bx,dx ;must be in BX to use indirectly
jmp b4[bx] ;jump to appropriate action routine
b4: dw b96 ;end of table is error, shouldn't happen
dw b10
dw b20
dw b30
dw b40
dw b50
dw b60
dw b70
dw b80
dw b90
b10: je b97 ;char is legal, finish up
jmp b1 ;else loop back and try again
b20: jbe b97
jmp b1
b30: ja b97
jmp b1
b40: je b95
jmp b1
b50: jbe b95
jmp b1
b60: ja b95
jmp b1
b70: je b98
jmp b1
b80: jbe b98
jmp b1
b90: ja b98
jmp b1
b95: xchg bx,dx ;get final address
dec bx ;make word
pop dx ;now get start of table
sub bx,dx ;and make offset
mov al,1 ;reset all the flags
or al,al ;like this
pop ax ;now restore the registers
pop dx
ret
b96: xchg bx,dx ;same except for carry flag set before RET
dec bx
pop dx
sub bx,dx
stc ;error indicator set here
pop ax
pop dx
ret
b97: xchg bx,dx
dec bx
pop dx
sub bx,dx
xor al,al ;set Z flag
pop ax
pop dx
ret
b98: xchg bx,dx
dec bx
pop dx
sub bx,dx
or al,80h ;set S flag
pop ax
pop dx
ret
;msec.asm - millisecond delay subroutine
;call with desired number of milliseconds (unsigned!) in CX
;Freeware, Uncopyrighted (U) 1993 John Lene Comeau
;Industrial Control Technology, experts in device drivers and
;utilities under VAX/VMS, MS-DOS, and PDP11/RSX11.
;Email jcomeau@world.std.com or 70641.57@compuserve.com
;
;this version written in A86, shareware by Eric Isaacson
;highly recommended for serious assembly language programmers
;
msec:
jcxz msec_quit ;if count zero, don't bother working
push ax ;save registers
push di
push cx
mov di,-1 ;init DI for calculation
mov al,0 ;to latch counter 0
cli ;don't worry, it's just for a few usecs...
out 43h,al ;send to timer command register
in al,40h ;get low byte of timer 0's count
mov ah,al ;store it...
in al,40h ;high byte waiting for us now...
sti ;OK to interrupt now
xchg al,ah ;now put in proper order
sub di,ax ;this is the reference value, see why later
;now we loop until timeout is reached
msec_loop:
cli ;disable interrupts during timer 0 read
xor al,al ;clear it to latch timer
out 43h,al ;send it
in al,40h ;get the count again, low byte first
mov ah,al
in al,40h
sti ;reenable interrupts
xchg al,ah
add ax,di ;add reference value
;you might be tempted to cut out this extra addition by adding
;the millisecond to the reference value in the initialization code
;above - but this will make the carry flag dependent upon the
;current value of the timer rather than just "timeout reached" -
;so we add the intermediate value first and let AX roll over if it
;has to without affecting the test which comes at the next addition.
;Otherwise this routine would work intermittently, hardly useful for
;reliable software.
;
;The timeout value was calculated from 1193180 Hz clock, which is
;standard on all PC's including the 8088 to the 80486. It counts
;down twice every cycle 0, fffe, fffc, ..., 4, 2, 0, fffe, etc.
;1193*2=2386=952h
add ax,952h ;then add millisecond timeout value
jc msec_loop ;if it rolled over, we're not there yet
add di,952h ;else add another msec to comparison value
loop msec_loop ;loop around till CX counts out
pop cx ;restore registers
pop di
pop ax
msec_quit:
ret
;
init_buffer:
pop ax ;get return address before messing with stack
mov bp,sp ;init byte pointer
add sp,buffer ;create the buffer...
jmp ax ;return to main routine
;
read_answer:
;let's give the CON device enough time to respond. If it's the
;actual console running ANSI.SYS it will be almost immediate. But
;if it's some weirdo running a VT-220 off his COM port with a CTTY
;command, at 300 baud yet, it may take a little longer. So let's
;give 20 ms maximum.
lea di,buffer[bp] ;point to buffer
mov dx,20 ;countdown register
mov cx,1 ;time for MSEC routine
i1: mov ah,0bh ;check if character is waiting
doscall
jc ret ;quit if error
inc al ;returned FF if so, this will set Z flag
jz i2 ;skip ahead and fetch it
call msec ;else delay a millisecond
dec dx ;dec the count
jz i8 ;quit if timeout
jmp i1 ;else loop
i2: mov ah,8 ;single character read, no echo, cooked
doscall ;get one character from STDIN
jc ret ;quit if program error
stosb ;store the character
cmp di,bp ;but check if we're at end of buffer
jz ret ;error if so
jmp i1 ;loop until timeout
i8: lea ax,buffer[bp] ;get buffer address again
sub di,ax ;see if we got anything
jz ret ;error if not
xchg ax,di ;count in AX, buffer address in DI
ret ;else return with count in DI